package com.example.rustfs.controller;

import com.example.rustfs.dto.ApiResponse;
import com.example.rustfs.dto.FileInfo;
import com.example.rustfs.service.FileService;
import com.example.rustfs.service.RecycleBinService;
import com.example.rustfs.service.RecentFileService;
import com.example.rustfs.service.UserService;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 文件管理控制器
 */
@Slf4j
@Controller
@RequiredArgsConstructor
public class FileController {

    private final FileService fileService;
    private final RecycleBinService recycleBinService;
    private final RecentFileService recentFileService;
    private final UserService userService;

    @PostConstruct
    public void init() {
        fileService.initBucket();
    }

    /**
     * 首页 - 文件列表
     */
    @GetMapping("/")
    public String index(@RequestParam(required = false, defaultValue = "") String path,
                       @RequestParam(required = false) String type,
                       HttpSession session,
                       Model model) {
        // 获取用户信息
        Long userId = (Long) session.getAttribute("userId");
        
        List<FileInfo> files;
        
        // 根据类型加载文件
        if ("recent".equals(type)) {
            // 最近使用
            files = recentFileService.getRecentFiles(userId, 50);
            model.addAttribute("currentType", "recent");
            model.addAttribute("currentPath", "");
        } else if (type != null && !type.isEmpty()) {
            files = fileService.listAllFilesByType(type);
            model.addAttribute("currentType", type);
            model.addAttribute("currentPath", "");
        } else {
            files = fileService.listFiles(path);
            model.addAttribute("currentPath", path);
            model.addAttribute("currentType", "all");
        }
        
        model.addAttribute("files", files);
        
        // 构建面包屑导航
        String[] pathParts = path.isEmpty() ? new String[0] : path.split("/");
        model.addAttribute("pathParts", pathParts);
        
        return "index";
    }

    /**
     * 上传文件
     */
    @PostMapping("/upload")
    @ResponseBody
    public ApiResponse<String> upload(@RequestParam("file") MultipartFile file,
                                      @RequestParam(required = false, defaultValue = "") String path,
                                      HttpSession session) {
        try {
            if (file.isEmpty()) {
                return ApiResponse.error("请选择要上传的文件");
            }
            Long userId = (Long) session.getAttribute("userId");
            fileService.uploadFile(file, path, userId);
            
            // 更新存储空间使用量
            long storageUsed = fileService.calculateUserStorageUsed(userId);
            userService.updateStorageUsed(userId, storageUsed);
            
            return ApiResponse.success("文件上传成功");
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return ApiResponse.error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 下载文件
     */
    @GetMapping("/download")
    public ResponseEntity<Resource> download(@RequestParam String key) {
        try {
            byte[] data = fileService.downloadFile(key);
            ByteArrayResource resource = new ByteArrayResource(data);

            String fileName = key.substring(key.lastIndexOf("/") + 1);
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20");

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedFileName)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .contentLength(data.length)
                    .body(resource);
        } catch (Exception e) {
            log.error("文件下载失败", e);
            return ResponseEntity.internalServerError().build();
        }
    }
    
    /**
     * 预览文件
     */
    @GetMapping("/preview")
    public ResponseEntity<Resource> preview(@RequestParam String key, HttpSession session) {
        try {
            byte[] data = fileService.downloadFile(key);
            ByteArrayResource resource = new ByteArrayResource(data);

            String fileName = key.substring(key.lastIndexOf("/") + 1);
            String ext = getFileExtension(fileName).toLowerCase();
            
            // 添加到最近使用
            Long userId = (Long) session.getAttribute("userId");
            if (userId != null) {
                recentFileService.addRecentFile(userId, key, fileName, (long) data.length);
            }
            
            // 根据文件类型设置Content-Type
            MediaType mediaType = getMediaType(ext);

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename*=UTF-8''" + 
                            URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20"))
                    .contentType(mediaType)
                    .contentLength(data.length)
                    .body(resource);
        } catch (Exception e) {
            log.error("文件预览失败", e);
            return ResponseEntity.internalServerError().build();
        }
    }
    
    /**
     * 获取文件MIME类型
     */
    private MediaType getMediaType(String ext) {
        return switch (ext) {
            // 图片
            case "jpg", "jpeg" -> MediaType.IMAGE_JPEG;
            case "png" -> MediaType.IMAGE_PNG;
            case "gif" -> MediaType.IMAGE_GIF;
            case "bmp" -> MediaType.parseMediaType("image/bmp");
            case "webp" -> MediaType.parseMediaType("image/webp");
            case "svg" -> MediaType.parseMediaType("image/svg+xml");
            
            // 视频
            case "mp4" -> MediaType.parseMediaType("video/mp4");
            case "webm" -> MediaType.parseMediaType("video/webm");
            case "ogv" -> MediaType.parseMediaType("video/ogg");
            case "avi" -> MediaType.parseMediaType("video/x-msvideo");
            case "mov" -> MediaType.parseMediaType("video/quicktime");
            
            // 音频
            case "mp3" -> MediaType.parseMediaType("audio/mpeg");
            case "wav" -> MediaType.parseMediaType("audio/wav");
            case "m4a" -> MediaType.parseMediaType("audio/mp4");
            case "flac" -> MediaType.parseMediaType("audio/flac");
            case "ogg", "oga" -> MediaType.parseMediaType("audio/ogg");
            case "aac" -> MediaType.parseMediaType("audio/aac");
            case "wma" -> MediaType.parseMediaType("audio/x-ms-wma");
            case "opus" -> MediaType.parseMediaType("audio/opus");
            
            // 文本
            case "txt" -> MediaType.TEXT_PLAIN;
            case "html", "htm" -> MediaType.TEXT_HTML;
            case "css" -> MediaType.parseMediaType("text/css");
            case "js" -> MediaType.parseMediaType("application/javascript");
            case "json" -> MediaType.APPLICATION_JSON;
            case "xml" -> MediaType.APPLICATION_XML;
            
            // PDF
            case "pdf" -> MediaType.APPLICATION_PDF;
            
            default -> MediaType.APPLICATION_OCTET_STREAM;
        };
    }
    
    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    /**
     * 删除文件（移至回收站）
     */
    @DeleteMapping("/delete")
    @ResponseBody
    public ApiResponse<String> delete(@RequestParam String key,
                                      @RequestParam(required = false, defaultValue = "false") boolean isFolder,
                                      @RequestParam(required = false) Long fileSize,
                                      HttpSession session) {
        try {
            Long userId = (Long) session.getAttribute("userId");
            String fileName = key.substring(key.lastIndexOf("/") + 1);
            
            if (isFolder) {
                // 文件夹暂不支持回收站，直接删除
                fileService.deleteFolder(key);
            } else {
                // 文件移至回收站
                recycleBinService.moveToRecycleBin(userId, key, fileName, fileSize != null ? fileSize : 0L);
                // 从最近使用中移除
                recentFileService.removeRecentFile(userId, key);
            }
            
            // 更新存储空间使用量
            long storageUsed = fileService.calculateUserStorageUsed(userId);
            userService.updateStorageUsed(userId, storageUsed);
            
            return ApiResponse.success("已移至回收站");
        } catch (Exception e) {
            log.error("删除失败", e);
            return ApiResponse.error("删除失败: " + e.getMessage());
        }
    }

    /**
     * 创建文件夹
     */
    @PostMapping("/folder")
    @ResponseBody
    public ApiResponse<String> createFolder(@RequestParam String folderName,
                                           @RequestParam(required = false, defaultValue = "") String path,
                                           HttpSession session) {
        try {
            if (folderName == null || folderName.trim().isEmpty()) {
                return ApiResponse.error("文件夹名称不能为空");
            }
            fileService.createFolder(path, folderName);
            
            // 更新存储空间使用量
            Long userId = (Long) session.getAttribute("userId");
            long storageUsed = fileService.calculateUserStorageUsed(userId);
            userService.updateStorageUsed(userId, storageUsed);
            
            return ApiResponse.success("文件夹创建成功");
        } catch (Exception e) {
            log.error("创建文件夹失败", e);
            return ApiResponse.error("创建文件夹失败: " + e.getMessage());
        }
    }

    /**
     * 重命名文件或文件夹
     */
    @PutMapping("/rename")
    @ResponseBody
    public ApiResponse<String> rename(@RequestParam String key,
                                     @RequestParam String newName) {
        try {
            if (newName == null || newName.trim().isEmpty()) {
                return ApiResponse.error("新名称不能为空");
            }
            fileService.rename(key, newName);
            return ApiResponse.success("重命名成功");
        } catch (Exception e) {
            log.error("重命名失败", e);
            return ApiResponse.error("重命名失败: " + e.getMessage());
        }
    }

    /**
     * 获取文件列表（API）
     */
    @GetMapping("/api/files")
    @ResponseBody
    public ApiResponse<List<FileInfo>> listFiles(@RequestParam(required = false, defaultValue = "") String path) {
        try {
            List<FileInfo> files = fileService.listFiles(path);
            return ApiResponse.success(files);
        } catch (Exception e) {
            log.error("获取文件列表失败", e);
            return ApiResponse.error("获取文件列表失败: " + e.getMessage());
        }
    }
}

